package com.devshephard.rpcframework.rpc.factory.channel;

import com.devshephard.rpcframework.rpc.component.tcp.netty.client.handler.RpcResponseMessageHandler;
import com.devshephard.rpcframework.rpc.component.tcp.netty.protocol.MessageCodecSharable;
import com.devshephard.rpcframework.rpc.component.tcp.netty.protocol.ProcotolFrameDecoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import java.util.concurrent.TimeUnit;

/**
 * Netty Channel单例工厂
 */
@Slf4j
public class SingletonClientChannelFactory {

    @Value("${rpc.request.address}")
    private static String requestServerAddress;  //远程访问服务端地址

    @Value("${rpc.request.port}")
    private static String requestServerPort;  //远程访问服务端端口

    private static Channel channel = null;
    private static final Object LOCK = new Object();


    // 获取唯一的 channel 对象
    public static Channel getChannel() {
        if (channel != null) {
            return channel;
        }
        synchronized (LOCK) { //  t2
            if (channel != null) { // t1
                return channel;
            }
            startClientChannel(requestServerAddress,requestServerPort);
            return channel;
        }
    }

    // 初始化 channel 方法
    public static void startClientChannel(String address,String port) {
        NioEventLoopGroup group = new NioEventLoopGroup();
        LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
        RpcResponseMessageHandler RPC_HANDLER = new RpcResponseMessageHandler();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(group);
        bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new ProcotolFrameDecoder());
                ch.pipeline().addLast(LOGGING_HANDLER);
                ch.pipeline().addLast(MESSAGE_CODEC);
                ch.pipeline().addLast(RPC_HANDLER);
            }
        });
        try {
            try{
                channel = bootstrap.connect(address, Integer.parseInt(port)).sync().channel();
            }catch (Exception e){
                e.printStackTrace();
            }

            channel.closeFuture().addListener(future -> {
                System.out.println("retry......");
                //断联重试
                SingletonClientChannelFactory.startClientChannel(address,port);
                //group.shutdownGracefully();
            });
        } catch (Exception e) {
            log.error("client error", e);
        }
    }

}
